"""CLI utilities for managing activation codes and database tasks."""
import asyncio
import csv
from pathlib import Path
from typing import List, Optional

import typer
from rich.console import Console

from app.database import Base, engine, AsyncSessionLocal
from app import crud

console = Console()
app = typer.Typer(help="Software licensing server management CLI")


async def _init_db_async():
    """Async helper to create database tables."""
    console.print("[yellow]Initializing database...[/yellow]")
    async with engine.begin() as conn:
        await conn.run_sync(Base.metadata.create_all)
    console.print("[green]Database initialized successfully.[/green]")


@app.command()
def init_db():
    """Create database tables if they don't exist."""
    asyncio.run(_init_db_async())


async def _create_codes_async(
    count: int, comment: str, duration_days: int, quota: int, csv_out: Optional[Path]
):
    """Async helper to batch generate activation codes."""
    codes_generated: List[str] = []
    real_duration = duration_days if duration_days > 0 else None

    console.print(f"[yellow]Generating {count} activation code(s)...[/yellow]")
    async with AsyncSessionLocal() as db:
        for _ in range(count):
            raw_code = await crud.create_activation_code_db(
                db, comment=comment, duration_days=real_duration, quota=quota
            )
            codes_generated.append(raw_code)
            console.print(f"  - Created: [cyan]{raw_code}[/cyan]")

    if csv_out:
        try:
            csv_out.parent.mkdir(parents=True, exist_ok=True)
            with csv_out.open("w", newline="", encoding="utf-8") as f:
                writer = csv.writer(f)
                writer.writerow(["activation_code"])
                for code in codes_generated:
                    writer.writerow([code])
            console.print(f"[green]Successfully exported codes to {csv_out}[/green]")
        except Exception as e:
            console.print(f"[red]Error writing to CSV: {e}[/red]")


@app.command()
def create_codes(
    count: int = typer.Option(1, "--count", "-c", help="Number of codes to generate."),
    comment: str = typer.Option(..., "--comment", "-m", help="A comment for the batch, e.g., customer name."),
    duration_days: int = typer.Option(365, "--days", "-d", help="Validity period in days. 0 for permanent."),
    quota: int = typer.Option(1, "--quota", "-q", help="Number of devices that can be activated."),
    csv_out: Optional[Path] = typer.Option(None, "--csv", help="Export the generated codes to a CSV file."),
):
    """Batch generate activation codes and optionally export to a CSV file."""
    asyncio.run(_create_codes_async(count, comment, duration_days, quota, csv_out))


async def _disable_code_async(code: str):
    """Async helper to disable a specific activation code."""
    async with AsyncSessionLocal() as db:
        success = await crud.disable_activation_code(db, code)
        if success:
            console.print(f"[green]Successfully disabled code: {code}[/green]")
        else:
            console.print(f"[red]Error: Could not find activation code '{code}'.[/red]")


@app.command()
def disable_code(code: str = typer.Argument(..., help="The activation code to disable.")):
    """Disable a specific activation code."""
    asyncio.run(_disable_code_async(code))


if __name__ == "__main__":
    app()
